home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
pascal
/
pcxkit.exe
/
PCX.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1992-03-26
|
24KB
|
628 lines
unit PCX;
(* version 3.1
by Peter Donnelly
1301 Ryan Street
Victoria BC
Canada V8T 4Y8
╒══════════════════════════════════════════════════════════════════════╕
│ May be copied freely. If you make practical use of this unit, │
│ a contribution of $10 or more would be appreciated. │
╘══════════════════════════════════════════════════════════════════════╛
This is a unit to read .PCX files and put them in displayable form. The
actual work of decoding the file and moving the data into memory is done
in assembler. Version 6 of Turbo Pascal is required for compilation.
The following display modes are supported:
Mode TP GraphMode Resolution Colors
~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~ ~~~~~~
$04 CGAC0 to C3 320 x 200 4
$06 CGAHi 640 x 200 2
$0D --- 320 x 200 16
$0E EGALo/VGALo 640 x 200 16
$10 EGAHi/VGAMed 640 x 350 16
$12 VGAHi 640 x 480 16
$13 --- 320 x 200 256
Mode $13 is supported only for files containing palette information,
i.e. not those produced by versions of Paintbrush earlier than 3.0.
The unit has been optimized for speed rather than flexibility or
compactness. In particular, the routine for displaying 16-color files
(which require the most computation) has been improved and now runs
about 50 percent faster than that in version 2.
It is assumed that the image is the width of and no taller than the
screen, and that you will set the correct display mode. No checking
is done to see that the .PCX file is compatible with the mode you've set.
You do, however, have to pass in the Turbo GraphDriver as a parameter
for all but 256-color files, so that the data will be interpreted
correctly. (For mode $0D, pass in 'EGA' or 'VGA', and see the comment on
palettes, below.)
For the CGA formats, the data is put into two buffers on the heap, from
where it can be moved into the two display memory banks. See SHOWCGA for
an example. You can of course alter the unit to move the data directly
into display memory, but there is no great saving in time.
For EGA and VGA formats, the data is written to page 0 of the video
buffer. This can easily be changed by setting "page_addr" to a different
value. Three different techniques of hiding the image while it is being
written are demonstrated in SHOWEGA, SHOWVGA, and SHOW256. If for any
reason you don't want to do this, you will want to rewrite the palette-
interpretation routines as separate procedures so you can set the
palette before decoding the image data.
References:
~~~~~~~~~~
Richard F. Ferraro, "Programmer's Guide to the EGA and VGA Cards"
(Addison-Wesley, 1988).
Richard Wilton, "Programmer's Guide to PC and PS/2 Video Systems"
(Microsoft, 1987).
"Technical Reference Manual [for Paintbrush]" (Zsoft, 1988). The
information in this booklet is also found in a file distributed with
at least some versions of Microsoft/PC Paintbrush.
Software:
~~~~~~~~
Besides the various incarnations of Paintbrush (ZSoft and Microsoft),
the excellent Deluxe Paint II Enhanced (Electronic Arts) can also create
files in .PCX format. Other graphics programs have conversion utilities.
*)
{ ======================================================================= }
INTERFACE
uses DOS, GRAPH;
type RGBrec = record
redval, greenval, blueval: byte;
end;
var pcxfilename: pathstr;
file_error: boolean;
pal: palettetype;
RGBpal: array[0..15] of RGBrec;
RGB256: array[0..255] of RGBrec;
page_addr: word;
bytes_per_line: word;
buff0, buff1: pointer;
{ CGA display memory banks: }
screenbuff0: array[0..7999] of byte absolute $b800:$0000;
screenbuff1: array[0..7999] of byte absolute $b800:$2000;
const page0 = $A000; { EGA/VGA display segment }
procedure SETMODE(mode: byte);
procedure SETREGISTERS(var palrec);
procedure READ_PCX_FILE(gdriver: integer; pfilename: pathstr);
procedure READ_PCX256(pfilename: pathstr);
{========================================================================}
IMPLEMENTATION
var scratch, abuff0, abuff1: pointer;
is_CGA, is_VGA: boolean;
repeatcount: byte;
datalength: word;
columncount, plane, video_index: word;
regs: registers;
const buffsize = 65521; { Largest possible }
{ -------------------------- BIOS calls --------------------------------- }
{ For modes not supported by the BGI, use SetMode to initialize the
graphics. Since SetRGBPalette won't work if Turbo hasn't done the
graphics initialization itself, use SetRegisters to change the colors
in mode $13. }
procedure SETMODE(mode: byte);
begin
regs.ah:= 0; { BIOS set mode function }
regs.al:= mode; { Display mode }
intr($10, regs); { Call BIOS }
end;
procedure SETREGISTERS(var palrec);
{ Palrec is any string of 768 bytes containing the RGB data. }
begin
regs.ah:= $10; { BIOS color register function }
regs.al:= $12; { Subfunction }
regs.es:= seg(palrec); { Address of palette info. }
regs.dx:= ofs(palrec);
regs.bx:= 0; { First register to change }
regs.cx:= $100; { Number of registers to change }
intr($10, regs); { Call BIOS }
end;
{ ====================== EGA/VGA 16-color files ========================= }
procedure DECODE_16; assembler;
asm
(* Registers used:
AL data byte to be written to video
AH data bytes per scan line
BX end of input buffer
CL number of times data byte is to be written
DL current column in scan line
ES output segment
DI index into output buffer
DS segment of input buffer
SI index into input buffer
BP current color plane
*)
push bp
{ ----------------- Assembler procedure for 16-color files -------------- }
{ The first section is initialization done on each run through the
input buffer. }
@startproc:
mov bp, plane { plane in BP }
mov es, page_addr { video display segment }
mov di, video_index { index into video segment }
mov ah, byte ptr bytes_per_line { line length in AH }
mov dx, columncount { column counter }
mov bx, datalength { no. of bytes to read }
xor cx, cx { clean up CX for loop counter }
mov cl, repeatcount { count in CX }
push ds { save DS }
lds si, scratch { input buffer pointer in DS:SI }
{ We have to adjust datalength for comparison with SI. TP 6.0 pointers are
normalized, but the offset can still be 0 or 8. }
add bx, si
cld { clear DF for stosb }
cmp cl, 0 { was last byte a count? }
jne @multi_data { yes, so next is data }
jmp @getbyte { no, so find out what next is }
{ -------------- Procedure to write EGA/VGA image to video -------------- }
{ The data in the .PCX file is organized by color plane, by line; that is,
all the data for plane 0 for line 1, then for plane 1, line 1, etc.
Writing the data to display memory is just a matter of masking out the
other planes while one plane is being written to. This is done with the
map mask register in the sequencer. All the other weird and wonderful
registers in the EGA/VGA do just fine with their default settings, thank
goodness. }
@writebyte:
stosb { AL into ES:DI, inc DI }
inc dl { increment column }
cmp